﻿using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Media;
using Microsoft.Win32;
using Mido.Properties;
using Mido.Utils.Mvvm;
using System;
using System.Linq;

namespace Mido.UiModules.SettingsModule
{
    public class SettingsViewModel : ViewModelBase
    {
        private readonly SettingsModel _model;
        
        public string Text
        {
            get { return _model.Text; }
            set
            {
                if (_model.Text == value)
                    return;

                _model.Text = value;

                RaisePropertyChanged("TextAlignmentVisibility");
                RaisePropertyChanged("TextEditorAligment");
            }
        }

        public FontFamily FontName
        {
            get { return new FontFamily(_model.FontName); }
            set
            {
                _model.FontName = value.Source;
                RaisePropertyChanged("FontName");
            }
        }

        public int Opacity
        {
            get { return _model.Opacity; }
            set
            {
                _model.Opacity = value;
                RaisePropertyChanged("OpacityTitle");
            }
        }

        public string OpacityTitle
        {
            get { return string.Format(Resources.SettingsViewModel_OpacityTitle_Opacity___0__, Opacity); }
        }

        public int FontSize
        {
            get { return _model.FontSize; }
            set { _model.FontSize = value; }
        }

        public TextAlignment TextAlignment
        {
            get { return _model.TextAlignment; }
            set
            {
                _model.TextAlignment = value;
                RaisePropertyChanged("TextEditorAligment");
            }
        }

        public TextAlignment TextEditorAligment
        {
            get { return TextAlignmentVisibility == Visibility.Visible ? TextAlignment : TextAlignment.Left; }
        }

		public AngleDefinition WatermarkAngle
        {
            get { return new AngleDefinition(_model.WatermarkAngle); }
            set { _model.WatermarkAngle = value.Angle; }
        }

        public ColorDefinition Color
        {
            get { return ColorDefinition.AllColors.First(x => x.Color == _model.Color); }
            set { _model.Color = value.Color; }
        }

        public ColorDefinition Stroke
        {
            get { return ColorDefinition.AllColors.First(x => x.Color == _model.Stroke); }
            set { _model.Stroke = value.Color; }
        }

        public int StrokeWidth
        {
            get { return _model.StrokeWidth; }
            set { _model.StrokeWidth = value; }
        }

        public bool IsBold
        {
            get { return _model.IsBold; }
            set { _model.IsBold = value; }
        }

        public bool IsItalic
        {
            get { return _model.IsItalic; }
            set { _model.IsItalic = value; }
        }

        public bool IsUnderline
        {
            get { return _model.IsUnderline; }
            set { _model.IsUnderline = value; }
        }

        public bool IsSettingsShown
        {
            get { return _model.IsSettingsShown; }
            set { _model.IsSettingsShown = value; }
        }
        
        public WatermarkSide Side
        {
            get { return _model.Side; }
            set { _model.Side = value; }
        }

        public int MaxWidth
        {
            get { return _model.MaxWidth; }
            set { _model.MaxWidth = value; }
        }

        public int MaxHeight
        {
            get { return _model.MaxHeight; }
            set { _model.MaxHeight = value; }
        }

		public int RelativeImageSize
        {
			get { return _model.RelativeImageSize; }
			set { _model.RelativeImageSize = value; }
        }

	    public FontSizeType FontSizeType
	    {
			get { return _model.FontSizeType; }
			set { _model.FontSizeType = value; }
	    }

		public FontSizeType ImageSizeType
	    {
			get { return _model.ImageSizeType; }
			set { _model.ImageSizeType = value; }
	    }

        public bool KeepOriginalSize
        {
            get { return _model.KeepOriginalSize; }
            set
            {
                if (_model.KeepOriginalSize == value)
                    return;

                _model.KeepOriginalSize = value;
                RaisePropertyChanged("ResizeOptionsVisibility");
            }
        }

        public Visibility ResizeOptionsVisibility
        {
            get { return KeepOriginalSize ? Visibility.Collapsed : Visibility.Visible; }
        }

        public ContentType ContentType
        {
            get { return _model.ContentType; }
            set
            {
                if (_model.ContentType == value)
                    return;

                _model.ContentType = value;
                RaisePropertyChanged("ImageEditorVisibility");
                RaisePropertyChanged("TextEditorVisibility");
            }
        }

        public Visibility ImageEditorVisibility
        {
            get { return ContentType != ContentType.OnlyText ? Visibility.Visible : Visibility.Collapsed; }
        }

        public Visibility TextEditorVisibility
        {
            get { return ContentType != ContentType.OnlyImage ? Visibility.Visible : Visibility.Collapsed; }
        }

        public string ImagePath
        {
            get
            {
				if (string.IsNullOrEmpty(_model.ImagePath))
					return "None";

	            return _model.ImagePath;
            }
        }

        public string ImageFileName
        {
            get
            {
				if (string.IsNullOrEmpty(_model.ImagePath))
					return "None";

	            return Path.GetFileName(_model.ImagePath);
            }
        }

        public Tuple<WatermarkSide, string>[] PossibleSides
        {
            get
            {
	            return new[]
		        {
					new Tuple<WatermarkSide, string>(WatermarkSide.LeftTop, Resources.SettingsViewModel_PossibleSides_Left_Top),
			        new Tuple<WatermarkSide, string>(WatermarkSide.CenterTop, Resources.SettingsViewModel_PossibleSides_Center_Top),
			        new Tuple<WatermarkSide, string>(WatermarkSide.RightTop, Resources.SettingsViewModel_PossibleSides_Right_Top),
			        new Tuple<WatermarkSide, string>(WatermarkSide.LeftCenter, Resources.SettingsViewModel_PossibleSides_Left_Center),
			        new Tuple<WatermarkSide, string>(WatermarkSide.CenterCenter, Resources.SettingsViewModel_PossibleSides_Center_Center),
			        new Tuple<WatermarkSide, string>(WatermarkSide.RightCenter, Resources.SettingsViewModel_PossibleSides_Right_Center),
			        new Tuple<WatermarkSide, string>(WatermarkSide.LeftBottom, Resources.SettingsViewModel_PossibleSides_Left_Bottom),
			        new Tuple<WatermarkSide, string>(WatermarkSide.CenterBottom, Resources.SettingsViewModel_PossibleSides_Center_Bottom),
			        new Tuple<WatermarkSide, string>(WatermarkSide.RightBottom, Resources.SettingsViewModel_PossibleSides_Right_Bottom)
				};
            }
        }

		public Dictionary<ContentType, string> PossibleContentTypes
        {
            get
            {
				return new Dictionary<ContentType, string>()
				{
					{ ContentType.ImageBeforeText, Resources.SettingsViewModel_PossibleContentTypes_Image_Before_Text },
					{ ContentType.TextBeforeImage, Resources.SettingsViewModel_PossibleContentTypes_Text_Before_Image },
					{ ContentType.OnlyImage, Resources.SettingsViewModel_PossibleContentTypes_Only_Image },
					{ ContentType.OnlyText, Resources.SettingsViewModel_PossibleContentTypes_Only_Text },
				};
            }
        }

		public Dictionary<TextAlignment, string> AllTextAlignment
        {
            get
            {
	            return new Dictionary<TextAlignment, string>()
		        {
					{ TextAlignment.Center, Resources.SettingsViewModel_AllTextAlignment_Center },
			        { TextAlignment.Justify, Resources.SettingsViewModel_AllTextAlignment_Justify },
			        { TextAlignment.Left, Resources.SettingsViewModel_AllTextAlignment_Left },
			        { TextAlignment.Right, Resources.SettingsViewModel_AllTextAlignment_Right },
		        };
            }
        }

		public Dictionary<FontSizeType, string> AllFontSizeTypes
        {
			get
			{
				return new Dictionary<FontSizeType, string>
				{
					{ FontSizeType.Percents, Resources.SettingsViewModel_AllFontSizeTypes_Percents },
					{ FontSizeType.Pixels, Resources.SettingsViewModel_AllFontSizeTypes_Pixels },
				};
			}
        }

        public Visibility TextAlignmentVisibility
        {
            get { return Text.Contains('\n') ? Visibility.Visible : Visibility.Collapsed; }
        }

        public Array PossibleWatermarkAngle
        {
            get { return AngleDefinition.AllAngles; }
        }

        public SettingsViewModel(SettingsModel model)
        {
            if (model == null) 
                throw new ArgumentNullException("model");

            _model = model;
        }
        
        public static SettingsViewModel Designer
        {
            get
            {
                SettingsModel settings = new SettingsModel
                {
                    Text = "Mido" + Environment.NewLine + "http://mido.codeplex.com",
                    ImagePath = @"d:\image.png",
                    KeepOriginalSize = false,
                    ContentType = ContentType.ImageBeforeText
                };

                return new SettingsViewModel(settings);
            }
        }

        public SimpleCommand OpenWatermarkImageCommand
        {
            get { return new SimpleCommand(OnOpenWatermarkImageCommand); }
        }

        private void OnOpenWatermarkImageCommand()
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = "Image Files(*.BMP;*.JPG;*.JPEG;*.PNG)|*.BMP;*.JPG;*.JPEG;*.PNG|All files (*.*)|*.*";

            if (dialog.ShowDialog(Application.Current.MainWindow).Value)
            {
	            _model.ImagePath = dialog.FileName;
				RaisePropertyChanged("ImagePath");
				RaisePropertyChanged("ImageFileName");
            }
        }
    }

	public class AngleDefinition
	{
		private static readonly AngleDefinition[] _allAngles = GetAllAngleDefinitions();
		
		private readonly WatermarkAngle _angle;

		public AngleDefinition(WatermarkAngle angle)
		{
			_angle = angle;
		}

		private static AngleDefinition[] GetAllAngleDefinitions()
		{
			return new[]
			{
				new AngleDefinition(WatermarkAngle.a0),
				new AngleDefinition(WatermarkAngle.a90),
				new AngleDefinition(WatermarkAngle.a180),
				new AngleDefinition(WatermarkAngle.a270)
			};
		}

		public WatermarkAngle Angle
		{
			get { return _angle; }
		}

		public static AngleDefinition[] AllAngles
		{
			get { return _allAngles; }
		}

		public override string ToString()
		{
			if (_angle == WatermarkAngle.a0)
				return "0°";
			if (_angle == WatermarkAngle.a90)
				return "90°";
			if (_angle == WatermarkAngle.a180)
				return "180°";
			if (_angle == WatermarkAngle.a270)
				return "270°";

			throw new InvalidOperationException();
		}

		public override bool Equals(object obj)
		{
			return _angle.Equals(((AngleDefinition)obj).Angle);
		}

		public override int GetHashCode()
		{
			return _angle.GetHashCode();
		}
	}

    public class ColorDefinition
    {
        private static readonly IList<ColorDefinition> _allColors = GetAllColors();

        private readonly string _colorName;
        private readonly Color _color;

        public static IList<ColorDefinition> AllColors
        {
            get { return _allColors; }
        }

        public string Name
        {
            get { return _colorName; }
        }

        public Color Color
        {
            get { return _color; }
        }

        private ColorDefinition(string colorName, Color color)
        {
            if (string.IsNullOrEmpty(colorName))
                throw new ArgumentNullException("colorName");

            _colorName = colorName;
            _color = color;
        }

        private static IList<ColorDefinition> GetAllColors()
        {
            string[] names = typeof(Colors).GetProperties().Select(x => x.Name).ToArray();
            ColorDefinition[] result = new ColorDefinition[names.Length];

            ColorConverter converter = new ColorConverter();

            for (int index = 0; index < result.Length; index++)
            {
                string colorName = names[index];
                Color color = (Color)converter.ConvertFrom(colorName);

                result[index] = new ColorDefinition(colorName, color);
            }

            return result;
        }

        public override string ToString()
        {
            return _colorName;
        }
    }
}
